package Thread;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.PriorityBlockingQueue;

class MyTask implements Comparable<MyTask>{
    //两个属性
    //1.要完成的任务
    //2.完成这个任务需要等待的时间
   volatile public Runnable runnable;
   volatile public long time;

    public MyTask(Runnable runnable,long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis()+delay;
        //当前实际的时间戳加上指定的时间,就是该任务实际执行的时间
    }

    @Override
    public int compareTo(MyTask o) {
        //每次去出的是取出时间最少的
        return (int)(time - o.time);
    }
}
class MyTimer{
    //创建一个锁对象
    Object locker = new Object();
   PriorityBlockingQueue <MyTask> blockingDeque = new PriorityBlockingQueue<>();
      public void schedule(Runnable runnable,long delay) throws InterruptedException {
         //根据这两个属性构造MyTask
          //不可以将synchronized放在这里,因为blockingDeque.take正在阻塞中,但是锁没有释放这样就会产生死锁
            MyTask myTask = new MyTask(runnable, delay);
            blockingDeque.put(myTask);
          synchronized (locker){
              locker.notify();
        }

     }
    //在这里构造线程
     public MyTimer() {
             Thread t= new Thread(()->{
                 synchronized (locker){

                     while (true) {
//                         synchronized (locker){

                         try {
                                 //如果没有就阻塞
                             MyTask myTask = blockingDeque.take();
                             //curTime当前时间
                             long curTime = System.currentTimeMillis();
                             if (myTask.time <= curTime) {
                                 myTask.runnable.run();
                             } else {
                                 //继续等待
                                     //如果没有,就等待time时间到
                                 blockingDeque.put(myTask);
                                 //如果不加入notify就会产生忙等现象
                                     locker.wait(myTask.time - curTime);
                                //如果没有notify就会等时间结束后重新读取新的MyTask
                                 //如果有notify就会直接唤醒wait,此时MyTask就是新一轮的时间最短的任务

                                }
                         } catch (InterruptedException e) {
                             e.printStackTrace();
                         }
                         }
                 }
             });
             t.start();


    }
}
public class ThreadDemo20 {
    //自己实现定时器
    public static void main(String[] args) throws InterruptedException {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello4");
            }
        },4000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello3");
            }
        },3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello2");
            }
        },2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello1");
            }
        },1000);
        System.out.println("hello");
    }
}
